package nl.utwente.ewi.hmi.multitouch.analysis.segmentation;

import gnu.trove.TIntIntHashMap;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.util.Set;

import javax.swing.JFrame;
import javax.swing.JPanel;

import nl.utwente.ewi.hmi.multitouch.Tangible;
import nl.utwente.ewi.hmi.multitouch.TouchDeviceInfo;
import nl.utwente.ewi.hmi.multitouch.analysis.Segment;
import nl.utwente.ewi.hmi.multitouch.io.TouchStream.Frame;
import nl.utwente.ewi.hmi.multitouch.io.TouchStream.FrameBuffer;
import nl.utwente.ewi.hmi.multitouch.io.TouchStream.TouchType;

public class ContourTracingSegmentation extends FrameSegmentation {

	private int[] labels = null;
	
	private TIntIntHashMap xs = null;
	private TIntIntHashMap ys = null;
	
	private Dimension size = null;
	
	public ContourTracingSegmentation(TouchDeviceInfo touchDeviceInfo) {
		super(touchDeviceInfo);

		this.size = touchDeviceInfo.getSize();

		labels = new int[size.width * size.height];
		
		xs = new TIntIntHashMap(size.width + size.height);
		ys = new TIntIntHashMap(size.width + size.height);

	}

	public Set<Segment> segment(FrameBuffer buffer) {
//		int frameCount = buffer.getFrameCount();
		Frame frame = buffer.getFrame(0);

		Tangible[] tangibles = frame.getTangibleMap();
		TouchType[] types = frame.getTouchTypeMap();

		int componentCount = 0;

		// for tangible
		for(int y = 0, i = 0; y < size.height; y++) {

			// als er op de 0e kolom al een tangible zit, markeer dan een rand vanaf de -1e kolom
			// markeer anders het gebied als component 1 en duw deze verder

			Tangible currentTangible = null;
			int currentLabel = 1;
			
			for(int x = 0; x < size.width; x++, i++) {
				int label = labels[i];
				
				// Label transition
				if(label != 0) {
					currentLabel = label;
					continue;
				}
				
				// use null for unlabeled part
				Tangible tangible = null;
				TouchType touchType = types[i];

				// but if the touchtype is positive or uncertain, adopt the tangible itself
				if(touchType == TouchType.POSITIVE || touchType == TouchType.UNCERTAIN) {
					tangible = tangibles[i];
				}
				
				// If the tangible did not change, propagate the current label to the right
				if(tangible == currentTangible) {
					labels[i] = currentLabel;
					continue;
				}

				// we have found a new contour
				if(label == 0 && tangible != currentTangible) {
					// which means that the previous pixel also denotes a new contour
					// and that the currentpixel also denotes a new contour

					// duw currentLabel + currentTangible rond vanaf i-1
					// duw label + tangible rond vanaf i
					
					// loop langs de buitenkant van component heen met de oude label + tangible
					// loop langs de binnenkant van het component heen met de nieuwe label + tangible
				}

				// duw label naar rechts
				currentTangible = tangible;
				currentLabel = label;

				label = labels[i];

			}
		}

		return null;
	}
	
	public static void main(String[] args) {
		final GeneralPath path = new GeneralPath();

		path.append(new Ellipse2D.Float(10, 10, 100, 100), false);
		path.setWindingRule(Path2D.WIND_EVEN_ODD);
		path.append(new Ellipse2D.Float(25, 25, 25, 25), false);
		path.append(new Ellipse2D.Float(65, 65, 25, 25), false);
		path.append(new Ellipse2D.Float(75, 75, 20, 20), false);
		path.closePath();

		JPanel jp = new JPanel() {

			
			@Override
			public void paint(Graphics g) {
				super.paint(g);
				Graphics2D g2d = (Graphics2D) g;
				g2d.setColor(Color.red);
				Path2D newPath = new Path2D.Float();
				newPath.setWindingRule(Path2D.WIND_EVEN_ODD);

//				newPath.append(path.getPathIterator(new AffineTransform()), true);
				newPath.append(path.getPathIterator(new AffineTransform(), 10), false);
				g2d.fill(newPath);
			}
		};
		
		JFrame frame = new JFrame();
		frame.getContentPane().setLayout(new BorderLayout());
		frame.getContentPane().add(jp);
		
		frame.pack();
		frame.setVisible(true);

	}
}
